פרק מחלקות ממשק המחלקה צריך גם לדעת להגדיר בתוכניתו מחלקות לפי הצורך. בפרק זה נלמד להגדיר מחלקה ולממשה על סמך ממשק נתון.

Similar documents
פרק מחלקות ממשק המחלקה צריך גם לדעת להגדיר בתוכניתו מחלקות לפי הצורך. בפרק זה נלמד להגדיר מחלקה ולממשה על סמך ממשק נתון.

ASP.Net MVC + Entity Framework Code First.

המבנה הגאומטרי של מידה

פרק עצמים א. טיפוסים חדשים ב. מצב של עצם

עץ תורשה מוגדר כך:שורש או שורש ושני בנים שכל אחד מהם עץ תורשה,כך שערך השורש גדול או שווה לסכום הנכדים(נכד-הוא רק בן של בן) נתון העץ הבא:

טכנולוגיית WPF מספקת למפתחים מודל תכנות מאוחד לחוויית בניית יישומיי

תצוגת LCD חיבור התצוגה לבקר. (Liquid Crystal Display) המערכת.

מבוא לתכנות - פיתוח משחקים ב Action Script 3.0

קשירות.s,t V שני צמתים,G=(V,E) קלט: גרף מכוון מ- s t ל- t ; אחרת.0 אם יש מסלול מכוון פלט: הערה: הגרף נתון בייצוג של רשימות סמיכות.

Rules Game (through lesson 30) by Nancy Decker Preparation: 1. Each rule board is immediately followed by at least three cards containing examples of

Patents Basics. Yehuda Binder. (For copies contact:

ניפוי שגיאות )Debug( מאת ישראל אברמוביץ

A R E Y O U R E A L L Y A W A K E?

מבוא לתכנות ב- JAVA תרגול 7

Practical Session No. 13 Amortized Analysis, Union/Find

זו מערכת ישרת זוית )קרטזית( אשר בה יש לנו 2 צירים מאונכים זה לזה. באותו מישור ניתן להגדיר נקודה על ידי זוית ורדיוס וקטור

מכונת מצבים סופית תרגול מס' 4. Moshe Malka & Ben lee Volk

שאלות חזרה לקראת מבחן מפמ"ר אינטרנט וסייבר

דיאגרמה לתיאור Classes

Reflection Session: Sustainability and Me

THINKING ABOUT REST THE ORIGIN OF SHABBOS

המחלקה למדעי המחשב, אוניברסיטת בן גוריון מבני נתונים, סמסטר אביב 2102 עבודת בית מספר - 2 מעשית

אנגלית שאלון ז' ג רסה א' הוראות לנבחן בהצלחה! )4( ההנחיות בשאלון זה מנוסחות בלשון זכר ומכוונות לנבחנות ולנבחנים כאחד. (MODULE G)

FILED: NEW YORK COUNTY CLERK 07/16/2014 INDEX NO /2014 NYSCEF DOC. NO. 102 RECEIVED NYSCEF: 07/16/2014 EXHIBIT 5

A JEW WALKS INTO A BAR: JEWISH IDENTITY IN NOT SUCH JEWISH PLACES

אנגלית (MODULE E) בהצלחה!

מבוא למחשב בשפת פייתון


מותאמת לסביבת. Visual C# 2005 Express שונות. ולבצע rename לשם המבוקש

תרגול מספר 9: בנאים, שיטות של אובייקטים והכמסה מבוא למדעי המחשב - סמסטר א' תשע"א,תרגול מס' 9. נושאי התרגול: this

כפתור רדיו בחירה בודדת מתוך רשימת אפשרויות

פרק רשימה א. ייצוג הרשימה

ANNEXURE "E1-1" FORM OF IRREVOCABLE STANDBY LETTER OF CREDIT PERFORMANCE OF CONTRACT (WHERE PRICES ARE NOT LINKED TO AN ESCALATION FORMULA)

תרגול 11 תור עץ חיפוש בינארי

לשרטוט חשמלי בתוכנת OrCad-Capture

פולימורפיזם. blog.csit.org.il מדעי המחשב

Hebrew Ulpan HEB Young Judaea Year Course in Israel American Jewish University College Initiative

מטוסים נופלים, כורים מתפוצצים זיכרון אוטומטי מקטסטרופות לומדים בניינים קורסים,

מספר השאלון: Thinking Skills נספח: כישורי חשיבה )לפרק ראשון ושני( א נ ג ל י ת (MODULE F) ספרות )מילון הראפס אנגלי-אנגלי-ערבי(

בהצלחה! (MODULE C) Hoffman, Y. (2014). The Universal English-Hebrew, Hebrew-English Dictionary

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE F) ספרות או: מילון אנגלי-ערבי / ערבי-אנגלי או: מילון אנגלי-אנגלי-ערבי

מבוא לתכנות - פיתוח משחקים ב Action Script 3.0

Structural Vs. Nominal Typing

Advisor Copy. Welcome the NCSYers to your session. Feel free to try a quick icebreaker to learn their names.

FILED: NEW YORK COUNTY CLERK 07/16/2014 INDEX NO /2014 NYSCEF DOC. NO. 134 RECEIVED NYSCEF: 07/16/2014 EXHIBIT 37

3. class attr_accessor def end 9. end puts "

א נ ג ל י ת בהצלחה! ב. משרד החינוך בגרות לנבחנים אקסטרניים )מילון הראפס אנגלי-אנגלי-ערבי( השימוש במילון אחר טעון אישור הפיקוח על הוראת האנגלית.

הצגת המשחק תלמידים משחקים סיום. פתיחה 12 min. min. min. min פתיחה. Copyright 2015

תאריך הבחינה: מבוא למדעי המחשב ד "ר פז כרמי פרופ' מייק קודיש ד "ר חן קיסר ד "ר צחי רוזן שם הקורס: מבוא למדעי המחשב מספר הקורס:

אנגלית ספרות בהצלחה! /המשך מעבר לדף/ נספח: כישורי חשיבה )לפרק ראשון ושני( או: מילון אנגלי-ערבי / ערבי-אנגלי או: מילון אנגלי-אנגלי-ערבי

זה. Nir Adar

Name Page 1 of 6. דף ט: This week s bechina starts at the two dots in the middle of

בוחן בתכנות בשפת C בצלחה

מותאמת לסביבת. Visual C# 2005 Express שונות. ולבצע rename לשם המבוקש

תוכן העניינים: פרק סדרות סיכום תכונות הסדרה החשבונית:... 2 תשובות סופיות:...8 סיכום תכונות הסדרה ההנדסית:...10

Expressions (ex 8) Wild World (ex 7) Cars (ex 9)

עד כה עסקנו בתוכניות שמתקדמות פקודה אחרי פקודה העתק ל- ax את הערך 3 העתק ל- bx את הערך 4 הוסף ל- ax את bx כפול את התוצאה ב- 2 והעתק ל- cx

התכנית הראשונה שלי

שאלון ו' הוראות לנבחן

שאלון ד' הוראות לנבחן

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות או מילון אנגלי-עברי-עברי-אנגלי

Visual C# Express יסודות מדעי המחשב 1 מהדורת עיצוב תשס"ו 2006 כתבה: יעל בילצ'יק (סופרין)

ãówh,é ËÓÉÔê ÌW W É Å t" Y w f É ËÓÉÑ É èw É f Ñ u ð NNM YóQ' ÌW W É Y ÉgO d óqk É w f ym Éd É u ð NNM ÌWNQMH uqo ð NNM ÌWNQMH

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי

תכנית סטארט עמותת יכולות, בשיתוף משרד החינוך א נ ג ל י ת שאלון א' Corresponds with Module A (Without Access to Information from Spoken Texts) גרסה א'

מבוא לאסמבלי מאת אופיר בק חלקים נרחבים ממאמר זה נכתבו בהשראת הספר "ארגון המחשב ושפת סף" אשר נכתב ע"י ברק גונן לתוכנית גבהים של משרד החינוך.

2007 Zindell Technologies, Ltd.

State Pattern מימוש מכונת מצבים (FSM) מבוא בעיה תמיכה ועדכונים עדכון מס' 48 מאי 2002

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE F) ספרות מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי

מבחן מועד ב' אנא קיראו היטב את ההראות שלהלן:

הבסיס כתיבת התכנית הראשונה שימוש במשתנים. הטיפוס הבסיסי object. הטיפוס הבסיסי string משפטי בקרה. שימוש ב- Enumerations. שימוש ב- Namespaces

נספח: כישורי חשיבה )לפרק ראשון ושני( אנגלית (MODULE D) ספרות או מילון אנגלי-עברי-עברי-אנגלי

תכנות מונחה עצמים סביבת Java

(MODULE E) ב ה צ ל ח ה!

Computer Structure. Exercise #1 יש להגיש את התשובות הסופיות על גבי טופס זה.

מספר ת"ז: יש לסמן את התשובה הטובה ביותר בתשובון. לא יינתן ניקוד על סימון תשובה בטופס הבחינה או במחברת הבחינה.

NATIONAL COUNCIL OF YOUNG ISRAEL. Shavuot Nation JEWISH EDITION. Compiled by Gabi Weinberg Teen Program Director

שאלון ו' הוראות לנבחן

חטיבת הביניים "יונתן" עבודה לקיץ באנגלית לבוגרי כיתה עבודה נעימה!

תרגול 8. Hash Tables

אנגלית שאלון ז' (MODULE G) ג רסה א' הוראות לנבחן )מילון אנגלי-ערבי / ערבי-אנגלי )

A Long Line for a Shorter Wait at the Supermarket

מושגים בסיסיים תלמידים והורים יקרים,

מבוא לרשתות - תרגול מס' 11 Transparent Bridges

יסודות מבני נתונים. תרגול :9 ערימה - Heap

גירסה C++ Tutorial Nir Adar עמוד 1

/ פתיחת החשבון הכרחית רק למרצה / מתרגל ונעשית רק בעת הכניסה הראשונה.

מספר השאלון: הצעת תשובות לשאלות בחינת הבגרות אנגלית (MODULE C) מילון אנגלי-אנגלי-עברי או מילון אנגלי-עברי-עברי-אנגלי قاموس إنجليزي - إنجليزي - عربي

תכנית סטארט עמותת יכולות, בשיתוף משרד החינוך א נ ג ל י ת שאלון ב' Corresponds with Module B גרסה ב' הוראות לנבחן

מדריך למשתמש בשירות. yes MultiRoom

The Connection between Town Planning, Public Taking (Appropriation) and Land Appraisal

מדדי מרכז הגדרה: מדדים סטטיסטיים המשקפים את הנטייה המרכזית של ההתפלגות מדדי מרכז מרכז ההתפלגות

Genetic Tests for Partners of CF patients

Translation from English by Nataly Shnaidman, Jerusalem

מדריך לניהול VPS טריפל סי מחשוב ענן בע"מ.

Name Page 1 of 5. דף ז. This week s bechina begins with the fifth wide line at the top of

הקדמה פרופ' מוטי בן-ארי המחלקה להוראת המדעים מכון ויצמן למדע

תכנות בטוח חלק ב ' מאת עידו קנר

ב. משרד החינוך בגרות לנבחנים אקסטרניים א נ ג ל י ת (MODULE B) הוראות מיוחדות: )2( בתום הבחינה החזר את השאלון למשגיח. בהצלחה!

Transcription:

- 37-3 פרק מחלקות ובנייה הגדרה בפרק הקודם ראינו כיצד ניתן להשתמש במחלקות קיימות על מנת ליצור עצמים, צריך גם לדעת להגדיר בתוכניתו מחלקות לפי הצורך. אך מתכנת בפרק זה נלמד להגדיר מחלקה ולממשה על סמך ממשק נתון. מהי מחלקה? מחלקה היא תבנית המגדירה טיפוס נתונים. מופעים של עצמים מהטיפוס המוגדר על ידי המחלקה. לפניכם ממשק המחלקה "דלי", שפגשנו בפרק הקודם. בעזרת הפעולה הבונה, ניתן לייצר ממשק המחלקה Bucket המחלקה מגדירה דלי שהוא בעל קיבולת. הדלי יכול להכיל כמות מים כלשהי עד קיבולת זו. Bucket (int capacity) void empty() boolean isempty() void fill (double amounttofill) int getcapacity() double getcurrentamount() void pourinto (Bucket bucketinto) String tostring() הפעולה בונה דלי ריק שקיבולתו היא הפרמטר.capacity הנחה: קיבולת הדלי היא מספר אי-שלילי הפעולה מרוקנת את הדלי הנוכחי הפעולה בודקת את מצב הדלי. אם הדלי הנוכחי ריק היא מחזירה "אמת", ואם לא היא מחזירה "שקר" הפעולה מקבלת כפרמטר כמות של מים וממלאת את הדלי הנוכחי בכמות זו. אם כמות המים היא מעבר לקיבולת הדלי, הדלי מתמלא ויתר המים נשפכים החוצה. הנחה: כמות המים היא מספר אי-שלילי הפעולה מחזירה את הקיבולת של הדלי הנוכחי הפעולה מחזירה את כמות המים הקיימת בדלי הנוכחי הפעולה מעבירה את כמות המים המקסימלית האפשרית מהדלי הנוכחי לדלי שהתקבל כפרמטר הפעולה מחזירה מחרוזת המתארת את הדלי הנוכחי בצורה הבאה: The capacity: <capacity> The current amount of water: <current amount of water>

- 38 - עיצוב תוכנה מבוסס עצמים ג'אווה מטרתנו הראשונה בפרק היא לכתוב את המחלקה Bucket על סמך הממשק הנתון. השגת המטרה תעשה על ידי ביצוע כל השלבים המתוארים בסעיפים שלהלן. א. הכרזה על מחלקה public class NameOfClass כאן ייכתב גוף המחלקה // הגדרת מחלקה חדשה נעשית באופן הבא: השורה המופיעה בראש ההכרזה נקראת כותרת המחלקה header).(class המילה השמורה public פותחת את כותרת המחלקה. זוהי אחת מהרשאות הגישה שג'אווה מציעה למתכנת. הסבר מפורט יותר על הרשאות גישה ועל מטרת השימוש בהן יופיע בסוף הפרק. המילה השמורה class מציינת כי זוהי הכרזה על מחלקה. אחריה יופיע שם המחלקה וסוגריים מסולסלים, שבתוכם ייכתב גוף המחלקה. חובה לקרוא למחלקה בשמו של הטיפוס שאותו היא מגדירה, לדוגמה:.class Bucket א. 1. מוסכמות הכתיבה בג'אווה, כמו בכל שפה, ישנן מוסכמות (conventions) לגבי סגנון הכתיבה בשפה. מוסכמות אלה הן כללים שהמתכנתים בשפה קיבלו על עצמם ומומלץ לציית להן. המוסכמות המקובלות באשר לשמות של מחלקות הן: שם מחלקה מתחיל באות גדולה, לדוגמה: class Bucket (המתחיל באות הגדולה B). קהילת המתכנתים בג'אווה מעודדת שימוש בשמות בעלי משמעות. כדי לאפשר קריאה נוחה של קוד (אפילו אם הוא מכיל שמות מורכבים וארוכים), ייכתב שם המחלקה כך שכל מילה חדשה תתחיל באות גדולה. לדוגמה: שמה של המחלקה "תולעת ורודה שלה נקודות כחולות", ייכתב כך: class PinkWormWithBlueDots במהלך פרק זה נכיר עוד מוסכמות. מדוע עלינו להיות כפופים למוסכמות אלה? התוכנית יכולה לרוץ גם אם נחרוג מהמוסכמות, אך למוסכמות חשיבות מרובה, והשימוש בהן הוא הכרחי כדי ליצור קוד מובן, קריא ונוח לשימוש.

פרק 3 מחלקות, הגדרה ובנייה - 39 - א. 2. קובץ חדש למחלקה החדשה את המחלקה החדשה נשמור בקובץ הנקרא:.Bucket.java כפי שכבר ראינו, כל מחלקה בג'אווה, המוגדרת כבעלת הרשאת גישה פומבית, חייבת להישמר בקובץ נפרד ששמו זהה לשם המחלקה, בתוספת הסיומת.'.java' שימו לב, קביעת שם הקובץ בצורה זו היא כלל הכרחי של השפה. ההתאמה בין שמות הקבצים לשמות המחלקות היא שמאפשרת למהדר לקשר ביניהם, ולמצוא באיזה קובץ שמורה כל מחלקה. ב. מצב של עצם לכל העצמים מטיפוס מחלקה מסוימת אותם האפיונים. הם נבדלים זה מזה במצבם, כלומר בערכי האפיונים שלהם. כדי לייצג 'מצב' של עצם יש לבחור תכונות שיוגדרו במחלקה. קיימת תלות בין הפעולות שעצם יכול לבצע לבין הייצוג שנבחר עבורו, ולכן לרוב נבחר את התכונות מתוך ידיעת השירותים שהעצם יכול לספק. המחלקה קופסה,,Box שבה עסקנו בפירוט בפרק הקודם, הגדירה טיפוס של קופסאות המאופיין על ידי שלוש תכונות: אורך, רוחב וגובה. כל אחד ממופעי המחלקה הוא בעל תכונות אלה, ומצבו נקבע על סמך הערכים שלהן. מצבם של מופעים יכול להיות שונה, אם ערכי תכונותיהם שונים זה מזה, אך גם אם כל ערכי התכונות שווים ומצב המופעים זהה לכאורה, עדיין כל מופע הוא עצם לעצמו. ב. 1. בחירת תכונות אם כך, התכונות יהיו הדבר הראשון שאותו נגדיר בכל מחלקה, ושלב זה ייקרא: ייצוג המחלקה. כדי לייצג את המחלקה, יש להחליט מהן התכונות שבהן אנו מעוניינים, בהתאם לבעיה שאנו מנסים לפתור. התכונות צריכות לייצג את האפיונים החשובים לנו לגבי מצב העצם. בבואנו לכתוב את המחלקה דלי, אנו צריכים לאפיין דלי בעזרת תכונות מסוימות. דליים נבדלים זה מזה בקיבולתם, ולכן סביר שתהיה לדלי תכונה בשם "קיבולת". דליים נבדלים גם בצבעם, בסוג החומר שממנו הם עשויים, במחירם וכדומה. בחירת התכונות לייצוג עצמים בתוכנית היא תהליך של הפשטה: אנו מייצגים ישויות תוך הדגשת תכונות מסוימות והתעלמות מאחרות, שאינן נראות לנו חשובות ליישום שאנו בונים. לכן לתוכנית המסוימת שבה אנו עוסקים נבחר רק את תכונות הדלי הנחוצות לנו. אם למשל התוכנית עוסקת במכירת דליים, אז מחיר הדלי הוא תכונה משמעותית ונחוצה. תכונה נוספת של דלי, כמות המים שבו, היא תכונה שיכולה לעניין אותנו אם התוכנית עוסקת במילוי דליים וריקונם. כאשר יוצרים עצם מטיפוס המחלקה, התכונות שלו מקבלות ערכים מסוימים. הפעולות השונות יכולות לגרום לשינוי ערכים אלה במהלך תוכנית. ייתכן שיופיעו בממשק פעולות הקובעות ו/או מחזירות את ערכיה של תכונה, עבור כל תכונה שנבחרה.

- 40 - עיצוב תוכנה מבוסס עצמים ג'אווה תכונות הן המשתנים הפנימיים של העצם, הקובעים את מצב העצם, ולמעשה את דרך ייצוג המחלקה. את הייצוג הזה נהוג להשאיר לשימוש המחלקה עצמה, ולהסתירו מהמשתמשים במחלקה בעזרת הגדרת התכונות כפרטיות.(private) public class Bucket תכונות (פרטיות ( // private int capacity; private double currentamount; ב. 2. הצהרה על תכונות טיפוס התכונה המייצגת את קיבולת הדלי הוא,int וזאת כיוון שאנו מניחים כי קיבולת הדלי היא מספר שלם (אפשר גם להניח אחרת). שם התכונה המייצגת את קיבולת הדלי הוא.capacity טיפוס התכונה המייצגת את כמות המים הנוכחית בדלי (שאינו מיוצג כמספר שלם בהכרח), הוא.currentAmount ושמה הוא,double המוסכמה שננהיג לגבי שמות התכונות היא אותה המוסכמה עבור שמות משתנים בכלל: השם ייכתב באותיות קטנות, למעט האות הראשונה של כל מילה פנימית חדשה, שתיכתב באות גדולה. ג. פעולה בונה מחלקה היא תבנית שממנה ניתן ליצור עצמים. כדי לעשות זאת צריך להקצות זיכרון עבור העצם ולאתחל את תכונותיו. שלבים אלה מתבצעים בעת הזימון של פעולה בונה של מחלקה והפעלתה. ג. 1. זימון הפעולה הבונה בפרק הקודם למדנו שיצירת עצם חדש מתבצעת בעזרת המילה השמורה.new אתחולו של העצם החדש מתבצע מיידית לאחר מכן, בעת זימון הפעולה הבונה. למשל, כדי ליצור דלי שקיבולתו 4 ליטרים ולהציבו במשתנה, נכתוב: Bucket b1 = new Bucket(4); מה קורה בפועל? הפקודה new באגף ימין מקצה מקום בזיכרון של המחשב עבור עצם בעל שתי תכונות: capacity מטיפוס,int ו- currentamount מטיפוס,double כפי שמפורט במחלקה. בשלב זה מאותחלות התכונות על פי ערכי ברירת המחדל של השפה. לאחר מכן מתבצעת הפעולה הבונה על העצם שנוצר, והיא מציבה ערכים לתכונות. הפעולה אינה חייבת לקבוע ערכים לכל התכונות. בשלב האחרון מתבצעת הצבה של העצם שנוצר, אותחל והוחזר מאגף ימין, לתוך המשתנה מטיפוס המחלקה שהוצהר באגף שמאל. אם הפעולה הבונה אינה מציבה באופן מפורש ערכים בתכונות של העצם, התכונות נשארות מאותחלות לערכי ברירת המחדל של ג'אווה. רצוי שלא להסתמך על ערכים אלה אלא לאתחל כל תכונה באופן מפורש.

פרק 3 מחלקות, הגדרה ובנייה - 41 - ג. 2. כותרת של פעולה בונה בג'אווה אין מילה שמורה המורה על כך שפעולה מסוימת היא פעולה בונה. לעומת זאת, יש מבנה כותרת מיוחד שבעזרתו המהדר מזהה פעולה בונה. שימו לב שהמבנה המיוחד של הכותרת הוא הדרך היחידה לזהות פעולה בונה, ולכן חשוב מאוד להקפיד עליו. מבנה הכותרת של פעולה בונה ייראה כך: 1. שם הפעולה, הזהה לשם המחלקה. 2. רשימת הפרמטרים של הפעולה, בסוגריים עגולים. את הכותרת מקדימה הרשאת הגישה (על פי רוב.(public רשימת הפרמטרים שם הפעולה הרשאת גישה public Bucket (int capacity) מהו ההיגיון המצוי בבסיס מבנה זה? הרשאת גישה מסוג public עצמים מטיפוס המחלקה. מאפשרת למחלקות אחרות להשתמש בפעולה הבונה וליצור הזהות בין שם הפעולה לשם המחלקה מאפשרת למהדר לדעת באיזו מחלקה מדובר, ולפי זה מהי תבנית העצם שצריך לבנות ומהו שטח הזיכרון הדרוש לעצם. כמו כן, זיהוי המחלקה מאפשר למהדר למצוא את הפעולה הבונה בהגדרת המחלקה. ולבסוף, כמו בכל פעולה, תיסגר כותרת הפעולה בסוגריים עגולים שיכילו את הפרמטרים הדרושים לביצוע הפעולה (אם יש כאלה), או יישארו ריקים (אם אין). ג. 3. מימוש הפעולה הבונה כדי לאתחל דלי חדש צריך לקבוע ערך התחלתי לתכונות שלו, שהן קיבולתו וכמות המים הנוכחית שבו. כיוון שהחלטנו שבעת הבנייה של דלי חדש, הדלי יהיה תמיד ריק, לפעולה יהיה רק פרמטר אחד, שהוא הפרמטר עבור הקיבולת. נעיין בקוד הפעולה הבונה של המחלקה :Bucket public Bucket(int capacity) this.capacity = capacity; this.currentamount = 0; הפנייה לעצם בתוך קוד המחלקה עצמה נעשית בעזרת המילה השמורה.this מילה זו מציינת את העצם הנוכחי. במקרה של פעולה בונה, זהו העצם שזה עתה נבנה.

- 42 - עיצוב תוכנה מבוסס עצמים ג'אווה מה שמתבצע בפעולה הבונה שכתובה למעלה הוא השמת הערך capacity (שהתקבל כפרמטר) בתכונה capacity של העצם, והשמת 0 בתכונה currentamount של העצם. מעכשיו והלאה, הערכים האלה שמורים בתכונות העצם וקובעים את מצבו. יתר הפעולות יכולות לגשת אל ערכים אלה, להשתמש בהם או לשנות אותם לפי הצורך. במימוש של פעולה בונה לעולם לא תופיע ההוראה,return כיוון שאין כאן יצירה והחזרה של עצם חדש, אלא אתחול מצב העצם שנוצר בעת ביצוע הפקודה.new הערה: בדוגמה שראינו, שם הפרמטר זהה לשם התכונה שהוא מאתחל. אנו כותבים זאת כך רק כדי להמחיש את הקשר בין הערך הנשלח לשם התכונה שאותה הוא מאתחל, אך אין זו חובה: שם הפרמטר אינו חייב להיות זהה לשם התכונה. ג. 4. פעולה בונה ללא פרמטרים ראינו כי פעולה בונה, בדומה לכל פעולה, יכולה לקבל פרמטרים. לעתים, נרצה לכתוב פעולה בונה שאינה מקבלת פרמטרים. כותרתה של פעולה בונה שכזו תיראה כך: public Bucket() פעולה כזו יכולה לאתחל את התכונות על פי קבועים שאינם מועברים על ידי המשתמש, כך: public Bucket() this.capacity = 10; this.currentamount = 0; public Bucket() אך היא יכולה גם שלא לאתחל במפורש את התכונות, באופן הזה: במקרה זה יאותחלו התכונות לפי ערכי ברירת המחדל של ג'אווה. עבור המחלקה דלי הן ה"קיבולת" והן "כמות המים הנוכחית" יאותחלו ל- 0, כלומר זו תהיה פעולה בונה שתיצור דליים "מעוותים" שגודלם 0. כדי למנוע יצירות מעוותות שכאלה עדיף ומומלץ לא לסמוך על ערכי ברירת המחדל של ג'אווה, אלא לאתחל תמיד את הערכים של התכונות באופן מפורש. בהמשך הפרק נראה כי ניתן להגדיר כמה פעולות בונות במחלקה אחת. ג. 5. פעולה בונה ברירת מחדל בג'אווה קיים מנגנון הדואג לכך שבכל מחלקה תופיע פעולה בונה, גם אם המתכנת שכח להוסיפה או נמנע מכך מסיבה כלשהי. במקרה כזה המנגנון מוסיף למחלקה פעולה בונה ללא פרמטרים וזו נקראת פעולה בונה ברירת מחדל constructor).(default הפעולה הבונה משאירה את ערכי

פרק 3 מחלקות, הגדרה ובנייה - 43 - ברירת המחדל של תכונות העצם כפי שנקבעו על ידי ג'אווה. מהלך זה אינו מומלץ, כפי שציינו לעיל. פעולה בונה ברירת מחדל מתווספת למחלקה באופן אוטומטי רק כאשר המתכנת לא הגדיר במחלקה אף פעולה בונה. את הפעולה הבונה הזו אי אפשר לראות במפורש בקוד המחלקה, אולם היא מהווה חלק מממשק המחלקה, ומחלקות אחרות יכולות להשתמש בה כדי ליצור עצמים חדשים. מנגנון ההוספה האוטומטי של פעולה בונה מונע קיום מחלקות שאין אפשרות לייצר מהן עצמים, אולם כאמור מומלץ לא לסמוך על מנגנון זה ולכלול בכל מחלקה לפחות פעולה בונה אחת (או יותר, כפי שנראה בהמשך), העונה על צורכי המחלקה. ד. תרשימים ד. 1. תרשימים של עצמים לאחר שהגדרנו איך נראה עצם מבחינת שטח הזיכרון המוקצה לו ומבחינת מצבו, שיעזור לנו להבין באופן ויזואלי את מצבם של עצמים שונים. נציג תרשים Bucket b1 = new Bucket(4); הפקודה: הקצתה שטח זיכרון לעצם מטיפוס דלי. לעצם שתי תכונות שערכיהן נקבעו בזמן ביצוע הפעולה הבונה והפניה אליו. ההפניה אליו מוצבת במשתנה b1. כל המידע הזה מתומצת בתרשים העצם הזה: b1 Bucket capacity 4 currentamount 0 Bucket b2 = new Bucket(); הפקודה: זימנה את הפעולה הבונה הראשונה המתוארת בסעיף ג. 4. שהיא פעולה בונה ללא פרמטרים וא תחלה את התכונות על פי קבועים כמתואר. בסיום הפקודה נוצר העצם המתואר בתרשים שלפנינו, וההפניה אליו מוצבת במשתנה b2: b2 Bucket capacity 10 currentamount 0 Bucket b3 = new Bucket(); ואילו הפקודה:

- 44 - עיצוב תוכנה מבוסס עצמים ג'אווה זימנה את הפעולה הבונה המתוארת בסעיף ג. 5. שהיא פעולה בונה ברירת מחדל וא תחלה את התכונות על פי ערכי ברירות המחדל של ג'אווה. בסיום הפקודה נוצר העצם המתואר בתרשים הבא, והפניה אליו מוצבת במשתנה b3: b3 Bucket capacity 0 currentamount 0 תרשימים נוספים שישמשו אותנו רבות ביחידה זו הם תרשימי UML לתיאור מחלקות, כפי שנראה בסעיף הבא. ד. 2. תרשימי UML דרך מקובלת להצגה תמציתית של מחלקות היא בעזרת שפת המידול Unified Modeling ) UML.(Language התרשים הבא מציג את המחלקה.Bucket התרשים מחולק לשלושה חלקים: שם המחלקה, תכונות ופעולות. בהמשך היחידה נציג פעמים רבות את תרשימי ה- UML ונחסוך בהסברים מילוליים ארוכים. המחלקה שם תכונות int capacity Bucket double currentamount Bucket (int capacity) void empty() boolean isempty() פעולות void fill (double amounttofill) int getcapacity() double getcurrentamount() void pourinto (Bucket bucketinto) String tostring() ה. פעולות נוספות בנוסף לפעולה בונה אחת או יותר, מוגדרות במחלקה פעולות נוספות. הפעולות האלה מופעלות על ידי עצמים הנוצרים מהמחלקה, ולרוב הן משתמשות בתכונות העצמים. נציג את יתר הפעולות בממשק המחלקה דלי. נזכיר כי הפנייה לעצמים בתוך קוד המחלקה נעשית באמצעות המילה השמורה this המציינת את העצם הנוכחי המבצע את הפעולות.

פרק 3 מחלקות, הגדרה ובנייה - 45 - public void empty() this.currentamount = 0; פעולה המרוקנת דלי: פעולה זו מרוקנת את הדלי, כלומר משנה את כמות המים הנוכחית ל- 0. מעכשיו כל פעולה שתשתמש בתכונה currentamount תקבל את הערך 0, עד שהדלי יתמלא מחדש. public boolean isempty() return this.currentamount == 0; פעולה הבודקת האם דלי ריק: פעולה זו בודקת האם דלי ריק, כלומר האם ערך התכונה currentamount של הדלי הנוכחי הוא 0. הפעולה מחזירה ערך בוליאני 'אמת' אם הדלי ריק, ו'שקר' אם אינו ריק. פעולה הממלאת דלי: פעולה זו אמורה להוסיף לכמות המים שבדלי את הכמות שהיא מקבלת כפרמטר. אם כמות המים המתקבלת לאחר ההוספה היא מעבר לקיבולת של הדלי, המים "יישפכו החוצה", כלומר יאבדו. public void fill(double amounttofill) אם הקיבולת של הדלי קטנה מהכמות החדשה שאמורה להתקבל בדלי // if (this.capacity < this.currentamount + amounttofill) מלא את הדלי עד הסוף // this.currentamount = this.capacity; else this.currentamount += amounttofill; public int getcapacity() return this.capacity; פעולה המאחזרת קיבולת: פעולה זו מחזירה את קיבולת הדלי.

- 46 - עיצוב תוכנה מבוסס עצמים ג'אווה public double getcurrentamount() return this.currentamount; פעולה המאחזרת את כמות המים: פעולה זו מחזירה את כמות המים הנוכחית בדלי. אם נפעיל את הפעולה על עצם שזה עתה נוצר, נקבל 0, כיוון שיצרנו את הדליים ריקים. לעומת זאת, אם לאחר שהעצם התמלא במים בעזרת הפעולה: ( ),fill נבקש את כמות המים הנוכחית בו, נקבל את כמות המים שקיימת בדלי לאחר פעולת ההוספה. פעולה המעבירה מים מהדלי הנוכחי לתוך דלי אחר: פעולה זו מקבלת כפרמטר עצם מטיפוס "דלי", שהוא עצם קיים שנוצר לפני זימון הפעולה. לתוך דלי זה היא צריכה לשפוך את המים שבדלי הנוכחי. הפעולה תמלא את דלי הפרמטר בכמות המקסימלית שאפשר להעביר אליו מתוך הדלי הנוכחי, מבלי שיישפכו מים החוצה. דוגמה public void pourinto(bucket bucketinto) double freespace = bucketinto.getcapacity() bucketinto.getcurrentamount(); if (this.currentamount < freespace) bucketinto.fill(this.currentamount); this.currentamount = 0; else bucketinto.fill(freespace); this.currentamount = freespace; נדגים את השימוש בפעולות שסקרנו עד לכאן: public static void main(string[] args) Bucket b1 = new Bucket(5); Bucket b2 = new Bucket(4); b1.fill(3); b2.fill(4); b2.pourinto(b1); נסקור את מצב הדליים בעזרת תרשימי עצמים.

פרק 3 מחלקות, הגדרה ובנייה - 47 - b1 Bucket b2 מצב הדליים בתום שתי הפעולות הראשונות: Bucket capacity currentamount capacity currentamount 5 0 4 0 b1 Bucket b2 מצב הדליים בתום שתי הפעולות הבאות: Bucket capacity currentamount capacity currentamount 5 3 4 4 מצב הדליים בתום הפעולה האחרונה: b1 Bucket b2 Bucket capacity currentamount capacity currentamount 5 5 4 2 כפי שאפשר לראות בתרשימי הדליים, נוצרו שני דליים: דלי אחד שקיבולתו 5, ודלי אחד שקיבולתו 4. בהתאם להגדרה של הפעולה הבונה, שני הדליים נוצרו ריקים. מילאנו את הדלי הראשון בשלושה ליטרים של מים ואת הדלי השני בארבעה ליטרים של מים. בפעולה האחרונה הדלי השני שופך את הכמות המקסימלית האפשרית של מים לתוך הדלי הראשון. כיוון שהדלי הראשון מכיל שלושה ליטרים של מים, נותר בו מקום לשני ליטרים נוספים. לכן לתוך הדלי הראשון יישפכו רק שני ליטרים מהדלי השני. בסיום התוכנית הדלי הראשון יהיה מלא, כלומר יהיו בו חמישה ליטרים של מים, ובדלי השני יהיו שני ליטרים. פעולה המאחזרת תיאור של דלי: פעולה זו בונה ומחזירה מחרוזת המתארת את העצם. המחרוזת מכילה מידע שהמתכנת מעוניין להציג לגבי העצם. בדרך כלל יהיו אלה ערכי כל התכונות של העצם או רק חלק מהן: public String tostring() String str = "The capacity: " + this.capacity + " \n" + "The current amount of water: " + this.currentamount; return str; הפעולה יצרה מחרוזת המכילה שרשור של ערכי התכונות של הדלי בצירוף הכותרות המתאימות. בשורה האחרונה הוחזרה המחרוזת כערך ההחזרה של הפעולה.

- 48 - עיצוב תוכנה מבוסס עצמים ג'אווה public static void main(string[] args) Bucket b1 = new Bucket(5); b1.fill (3); System.out.println(b1); פעולה זו שימושית מאוד כאשר רוצים להדפיס את תיאור המופע: בשורה הראשונה של הפעולה הראשית נוצר דלי שקיבולתו 5. בשורה השנייה מתמלא דלי זה בשלושה ליטרים של מים. בשורה האחרונה מזמן המופע b1 את הפעולה.toString() פעולה זו מחזירה את המחרוזת המתארת את המופע ואז מתבצעת ההדפסה. לסיום נראה את המחלקה Bucket בשלמותה: public class Bucket private int capacity; private double currentamount; public Bucket(int capacity) this.capacity = capacity; this.currentamount = 0; public void empty() this.currentamount = 0; public boolean isempty() return this.currentamount == 0; public void fill(double amounttofill) if (this.capacity < this.currentamount + amounttofill) this.currentamount = this.capacity; else this.currentamount += amounttofill; public int getcapacity() return this.capacity; public double getcurrentamount() return this.currentamount;

פרק 3 מחלקות, הגדרה ובנייה - 49 - public void pourinto(bucket bucketinto) double freespace = bucketinto.getcapacity() - bucketinto.getcurrentamount(); if (this.currentamount < freespace) bucketinto.fill(this.currentamount); this.currentamount = 0; else bucketinto.fill(freespace); this.currentamount -= freespace; public String tostring() String str = "The capacity: " + this.capacity + "\n" +"The current amount of water: " + this.currentamount; return str; ו. העמסת פעולות ניתן לכתוב באותה המחלקה כמה פעולות בעלות אותו השם, בתנאי שרשימת הפרמטרים שלהן שונה. השונות יכולה להיות במספר הפרמטרים, בטיפוסיהם או בסדר הופעת הפרמטרים בסוגריים. למשל אם נרצה להגדיר פעולה ששופכת מהדלי הנוכחי לדלי אחר כמות מים מוגדרת המועברת אליה כפרמטר, ואינה מעבירה את כל הכמות האפשרית, נוכל להגדיר פעולה שזו תהיה הכותרת שלה: public void pourinto(bucket bucketinto, double amounttopour) זאת למרות שיש כבר במחלקה פעולה בעלת שם זהה: public void pourinto(bucket bucketinto) משום שמספר הפרמטרים או סדר הופעתם שונה (במקרה זה מספר הפרמטרים), המהדר יודע לבחור את הפעולה הנכונה עבור כל זימון. למנגנון המאפשר להגדיר כמה פעולות בעלות אותו השם שהן נבדלות זו מזו ברשימת הפרמטרים שלהן קוראים העמסה.(overloading) שימו לב, השוני בין הכותרות של שתי הפעולות חייב להיות ברשימת הפרמטרים במספרם או בסדרם. שוני בטיפוס ערך ההחזרה אינו מספיק, כלומר אם נגדיר פעולה בשם: public int pourinto(bucket bucketinto)

- 50 - עיצוב תוכנה מבוסס עצמים ג'אווה הנבדלת מהפעולה הקיימת רק בטיפוס ערך ההחזרה, המהדר לא יקבל זאת. כיוון שזימון פעולה מאופיין רק על ידי שם הפעולה והפרמטרים המועברים אליה, המהדר אינו יכול להבדיל בין פעולות שונות בעלות אותו השם ואותם הפרמטרים רק על פי טיפוס ערך החזרה שונה, שכלל אינו כלול בזימון הפעולה. כך בזימון הזה: b1.pourinto(b2); אין למהדר מספיק מידע כדי להבדיל בין פעולה בעלת ערך החזרה int לבין פעולה בעלת ערך החזרה,void וכדי לדעת איזו פעולה מבין השתיים מזומנת. באמצעות מנגנון ההעמסה ניתן לכתוב פעולות בונות שונות בהתאם לרצון המתכנת. למשל אם רוצים להגדיר פעולה בונה שיוצרת דליים לא ריקים, אלא כאלה שבהם כמות מים התחלתית מסוימת, ניתן להגדיר פעולה בונה שזו כותרתה: public Bucket(int capacity, double currentamount) public Bucket() כמו כן ניתן להגדיר פעולה בונה ללא פרמטרים: כאשר מממשים פעולה זו, המתכנת יכול להחליט על ערכי ברירת מחדל משלו לתכונות. תזכורת: המהדר יגדיר באופן אוטומטי פעולה בונה ברירת מחדל רק אם במחלקה כלל לא הוגדרו פעולות בונות. לכן רצוי ומקובל שהמתכנת יגדיר לפחות פעולה בונה אחת בכל מחלקה. ו. 1. פעולה בונה מעתיקה יצירת עותק של עצם היא פעילות חשובה שמתכנתים נדרשים לה לא מעט. זכרו שפעולה בונה מאתחלת תכונות של עצם חדש שנוצר לפני זימונה. יצירת עותק נעשית בעזרת פעולה בונה המקבלת עצם קיים כפרמטר ומעתיקה את ערכי תכונותיו לעצם חדש. זוהי פעולה בונה כיוון שהיא מחזירה עצם חדש, מאותחל, מטיפוס המחלקה. לפעולה בונה שכזו קוראים פעולה בונה מעתיקה.(copy constructor) מנגנון ההעמסה הוא זה שיאפשר להוסיף לפעולות הבונות הקיימות במחלקות גם פעולות בונות מעתיקות. זכרו שבתוך המחלקה עצמה ניתן לפנות לתכונות הפרטיות של כל עצם מטיפוס המחלקה, ולכן הקוד של פעולה בונה מעתיקה המצורפת למחלקה Bucket ייראה כך: public Bucket(Bucket b1) this.capacity = b1.capacity; this.currentamount = b1.currentamount; כיוון שזו פעולה בונה, איננו יוצרים את העצם החדש בתוך מימוש הפעולה, אלא רק מאתחלים את תכונותיו שם. העצם נוצר באמצעות הפקודה new בעת זימון הפעולה: Bucket b1 = new Bucket(7, 2); Bucket b2 = new Bucket(b1);

פרק 3 מחלקות, הגדרה ובנייה - 51 - בשורה הראשונה נוצר עצם שקיבולתו 7 וכמות המים הנוכחית בו היא 2. עותק של העצם הזה, וההפניה אליו מוצבת ב- b2 : בשורה השנייה נוצר b1 Bucket b2 Bucket capacity currentamount capacity currentamount 7 2 7 2 ז. הכמסה עקרון ההכמסה (אנקפסולציה (encapsulation הוא מיסודותיו של תכנות מונחה עצמים. לפי עיקרון זה, עצם דומה לקופסה שחורה המספקת שירותים למשתמשים בה. מי שמשתמש בעצם, חייב להכיר את הממשק של הקופסה, כלומר את השירותים שהעצם יודע לספק. לעומת זאת, האופן שבו העצם מממש את השירותים הללו צריך להיות מוחבא בתוך הקופסה השחורה, נסתר מעין המשתמש. אנקפסולציה, או הכמסה, מבטאת שאיפה "לעטוף את המימוש בתוך קפסולה, או בכמוסה", ומכאן שמה. קל לראות כי עקרון ההכמסה אינו אלא עקרון הסתרת המידע, הגורס כי עצם צריך לחשוף בפני עצמים אחרים רק את ש ירותיו, ולהסתיר מהם את יתר הפרטים, את הייצוג ואת המימוש, שאינם חיוניים לצורך השימוש בשירותים האלה. עקרון ההכמסה א פשר לנו בפרק הקודם לצייר בעזרת הצב תרשימים שונים, מבלי לדעת מהן תכונותיו וכיצד הוא מבצע את תזוזותיו. די היה לנו להכיר את ממשק הפעולות כדי להפעיל את הצב כראוי. בסעיף זה נכיר מנגנון חשוב המאפשר הכמסה בג'אווה ונלמד איך משתמשים בו. ז. 1. הרשאות גישה.1.2 כאשר אנו מגדירים פעולה או תכונה, ובקיצור איבר, עלינו להחליט אילו עצמים יוכלו לגשת אליו. הרשאת גישה specifier) (access נקבעת על פי ההגדרה המופיעה במחלקה כחלק מהגדרת האיבר. בג'אווה קיימות כמה רמות של הרשאות גישה, בהן: הרשאת גישה פומבית (public) כאשר הגדרת האיבר כוללת את המילה השמורה,public עצמים מכל המחלקות בג'אווה יכולים לגשת אליו. הרשאת גישה פרטית (private) כאשר הגדרת האיבר כוללת את המילה השמורה,private ניתן לגשת לאיבר רק בקוד המחלקה שבה הוא מוגדר. המהדר יפסול כל גישה לאיבר כזה אם נעשתה מחוץ למחלקה. כל פנייה אל האיבר בתוך המחלקה תהיה חוקית. מהאמור לעיל נובע שניתן לגשת לאיבר של עצם בשני מקרים: אם האיבר מוגדר כפומבי. אם האיבר מוגדר כפרטי והגישה אליו היא מתוך הקוד של המחלקה שהוא מוגדר בה. דוגמה מוכרת לכך היא אתחול תכונות פרטיות בתוך פעולה בונה.

- 52 - עיצוב תוכנה מבוסס עצמים ג'אווה שימו לב, הגישה לאיבר תלויה בשני דברים: בהרשאת הגישה שלו ובמחלקה שממנה מנסים לגשת אליו. הדוגמה הבאה ממחישה בקצרה את הנאמר לעיל. בתוך המחלקה A ניתן לפנות ישירות לתכונה שהוגדרה כפרטית. מחוץ למחלקה A, ניתן לפנות רק אל איברים שהוגדרו כפומביים, כמו למשל אל הפעולה,first() אך לא ניתן לפנות ישירות לתכונה a1 שהוגדרה כפרטית, או לפעולה :domore( ) public class A private int a1; public int first() return this.a1++; private int domore() return --this.a1; לא חוקי public class B private A a3; public void doing() System.out.println ((this.a3).first()); System.out.println ((this.a3).a1); // לא חוקי ((this.a3).domore());// System.out.println ז. 2. למה משמשות הרשאות גישה? גישה מבוקרת לתכונות מחלקה נבנית כדי לתת תבנית יישומית להגדרה מופשטת, שמתכנת יצר עבור יישום כלשהו. כאשר מתכנת מגדיר עצמים שלהם הוא נזקק בתוכניתו, הוא מתחיל בהגדרת טיפוס מופשט, בהגדרת מצבם של מופעי הטיפוס ובהגדרת פעולות ממשק המאפשרות החזרת מידע ושינוי המצב של העצם. על פי ההגדרה של המצב והפעולות, על המתכנת לבחור בייצוג שיאפשר את מימושן של פעולות אלה. כך הוא יוכל לממש את הפעולות על פי הייצוג שבחר. הפעולות הן הדרך לפעול על עצמים ולשנות את מצבם. בדרך כלל לא מקובל לאפשר למשתמש לגשת אל התכונות ישירות, שלא דרך הפעולות. למשל, למחלקה דלי יש שתי תכונות: "קיבולת" ו"כמות המים הנוכחית". ההיגיון אומר שהתכונה הראשונה אינה ניתנת לשינוי: דלי שנוצר בקיבולת מסוימת יישאר בגודל זה. על מנת לעשות זאת ניתן להגדיר את התכונה הזאת כפרטית ולא לכתוב את הפעולה,setCapacity( ) המאפשרת לשנות את קיבולת הדלי. כך מבטיחים שקיבולת הדלי לא תוכל להשתנות על ידי המשתמשים במחלקה. לעומת זאת, התכונה "כמות המים הנוכחית" משתנה במשך ריצת התוכנית, כאשר ממלאים ומרוקנים את הדלי. השינויים בערך התכונה עצמה צריכים להתבצע במגבלות שמציבה התכונה "קיבולת" הדלי, שהרי לא ייתכן שכמות המים בדלי תהיה רבה יותר מהכמות שהדלי יכול להכיל

פרק 3 מחלקות, הגדרה ובנייה - 53 - ולא ייתכן שכמות המים תהיה מספר שלילי. הגדרת התכונה כפרטית, כך שעדכונה ייעשה רק בעזרת הפעולות,fill( ) pourinto( ) ו-() empty, מבטיחה שהתוכנית תרוץ בלי לחרוג מן המגבלות הנבדקות בקוד הפעולות. השימוש בהרשאות גישה מאפשר למתכנת המחלקה להבטיח שימוש תקין בעצמים של המחלקה שלו. מי שמשתמש במחלקה מוגבל לפעולות שהוגדרו עבורו, ואין לו גישה לתכונות עצמן. נציג כלל מקובל וחשוב: על פי רוב, אין לתת למשתמש גישה ישירה לתכונות של העצם. לכן אנו מגדירים את התכונות של העצם כפרטיות. הפרדה בין ממשק למימוש באמצעות הרשאות גישה יכול כותב המחלקה גם להפריד בצורה קלה בין ממשק המחלקה לבין המימוש שלה. האיברים הפומביים, המוגדרים באמצעות ההרשאה,public מרכיבים את ממשק המחלקה. עצמים ממחלקות אחרות יכולים לעבוד עם עצם ממחלקה זו ולתקשר עמו רק דרך ממשק זה, על ידי זימון פעולות פומביות או על ידי גישה לתכונות פומביות. לעומת זאת, האיברים הפרטיים, המוגדרים באמצעות ההרשאה, private משמשים רק למימוש המחלקה. זימון פעולות פרטיות או גישה לתכונות פרטיות אפשרי רק מתוך קוד המחלקה. להפרדה הברורה בין ממשק למימוש יתרון בולט: כיוון שעצמים של מחלקות אחרות אינם יכולים להשתמש באיברים הפרטיים של המחלקה, אנו יכולים לשנות ולשפר את המימוש שלה מעת לעת בלי לפגוע בתוכניות המשתמשות בה, כל עוד הממשק של המחלקה אינו משתנה. מכיוון שכל הפעולות המופיעות בממשק הן פעולות פומביות, איננו מציינים את הרשאת הגישה public בטבלאות הממשק לאורך היחידה, אבל בקוד המחלקות יש לכלול הרשאת גישה זו. מלבד הפעולות המופיעות בממשק, שבאמצעותן המחלקה מספקת את שירותיה, נמצא פעמים רבות פעולות נוספות, המסייעות לכותב המחלקה במימוש הפנימי של המחלקה. פעולות עזר אלה אינן צריכות להופיע בממשק המחלקה, והן יוגדרו כפרטיות משום שנועדו לכותב המחלקה בלבד. ז. 3. טיפוס נתונים מופשט בתחילת הסעיף ציינו כי עקרון ההכמסה הוא אחד מעקרונותיו של תכנות מונחה עצמים. עיקרון זה מחייב הפרדה מוחלטת בין ממשק למימוש, ויתרון אחד של הפרדה זו כבר פורט לעיל. כעת נצביע על יתרון חשוב נוסף של הפרדה זו. למדנו שדרך הייצוג של הטיפוסים המוגדרים על ידי המחלקות מוסתרת מעיני המשתמש והוא יכול להשתמש במופעי המחלקה רק בעזרת פעולות הממשק. לפיכך, ניתן להחליף את הייצוג של המחלקה ולהתאים את מימוש פעולותיה לייצוג החדש מבלי שהמשתמש יצטרך לשנות משהו בתוכניות שהשתמשו במחלקה זו. יתרה מכך, המשתמש כלל אינו צריך לדעת על שינוי הייצוג והמימוש. שינויים אלה יכולים להקל במקרים רבים על תחזוקת מערכות מחשב, על שינוי גרסאות תוכנה ועוד.

- 54 - עיצוב תוכנה מבוסס עצמים ג'אווה נדגים בקצרה: המחלקה Rectangle מגדירה מלבן שצלעותיו מקבילות למערכת הצירים. ניתן לייצג את המחלקה בעזרת ערכי הקואורדינטות של שתי נקודות: הקודקוד הימני התחתון של המלבן והקודקוד השמאלי העליון. כלומר ייצוג המחלקה ייעשה בעזרת ארבע תכונות שערכיהן יהיו מספרים: xrightbottom, yrightbottom, xlefttop, ylefttop הפעולות במחלקה ישתמשו בתכונות אלה לחישובים שונים, כגון חישוב שטח המלבן או היקפו. אם מטעמים כלשהם נחליט לשנות את ייצוג המחלקה ולייצגה בעזרת נקודת המרכז של המלבן, אורך המלבן ורוחבו, יהיה עלינו לשנות את כל אופן מימוש הפעולות, שכן הערכים שעליהן תתבססנה הפעולות ישתנו. שינויים אלה אינם מעניינים את המשתמש, שכן הפעולות לאחזור שטח מלבן, היקפו ומיקומו במערכת הצירים עדיין קיימות, והתוכנית שלו משתמשת רק בהן. כל זמן שמתכנת המחלקה ישמור על הממשק, הוא יכול לשנות את הייצוג הפנימי ואת המימוש של הפעולות מבלי שהמשתמש החיצוני יהיה מודע לכך, ואולי אף ייפגע מכך. טיפוס נתונים המוגדר רק על ידי הפעולות שניתן לבצע על מופעיו נקרא טיפוס נתונים מופשט.(abstract data type) ADT מחלקה הממומשת באופן שמסתיר לגמרי את דרך ייצוגה ואת המימוש שלה, וחושף רק את הפעולות שניתן לבצע על העצמים הנוצרים ממנה, היא מחלקה המגדירה טיפוס נתונים מופשט. בהמשך היחידה נחזור לדון בטיפוסי נתונים מופשטים, השימוש בהם. נרחיב את הגדרתם ונגלה את יתרונות ח. תיעוד מחלקה עד כאן הרבינו לדבר בשבח העבודה עם מחלקות דרך ממשקים, שהוא עיקרון מרכזי בתכנות מונחה עצמים. העבודה בעזרת ממשקים מאפשרת הפרדה מלאה בין ממשק למימוש ומייצגת את עקרון הסתרת המידע. איך מייצרים את הממשקים הללו? מה אמור להופיע בהם? ח. 1. כללי התיעוד ממשק טוב אמור להכיל את המידע הרלוונטי למשתמש במחלקה, מבלי לחשוף כלל את אופן המימוש שלה. ממשק צריך לספק עבור כל פעולה תיעוד מדויק לגבי מה היא מבצעת, אך הוא אינו מספק מידע על איך היא מבצעת זאת. בנוסף הממשק מספק מידע על הערכים שכל פעולה מקבלת, על ערך ההחזרה, על מקרי הגבול שיש לשים לב אליהם ועל ערכי הקצה הבעייתיים שיש להימנע מלהשתמש בהם. ככל שהממשק יהיה מפורט ומדויק יותר, כך השימוש במחלקה יהיה קל ויעיל יותר (במקביל יש להיזהר מעודף פירוט המעמיס על המשתמש נתונים מיותרים)..1

פרק 3 מחלקות, הגדרה ובנייה - 55 -.2 בג'אווה הממשק נוצר מתיעוד שכתב יוצר המחלקה למטרה זו. ג'אווה מספקת מנגנון, הנקרא,Javadoc המסוגל להפוך את כל התיעוד המשמעותי למסמך מסוג.HTML בעבר עבדתם עם.3.4 מסמכים כאלה כאשר עיינתם ב- JavaAPI של מחלקות נתונות,Bucket) Point,String ועוד). כל הערה פנימית שמיועדת לעיני המתכנת בלבד תופיע בקוד המחלקה לאחר סימן // או בין הסימן */ בתחילתה, והסימן /* בסופה (הערה כזו יכולה להתפרס על כמה שורות). הערה כזו אינה תורמת לממשק. כל ההסברים למחלקה על מהותה, ופעולות פומביות אחרות הקיימות בה, על תכונות פומביות אם קיימות בה, ועל פרמטרים שהן מקבלות, ייכתבו באופן הזה: בתחילתם ייכתב הסימן **/ ובסופן הסימן /*. תחימת ההערה בין הסימנים /* ו- /** בהערה כדי להוציאו מגוף הקוד אל דף הממשק. על פעולות בונות וכן מקרי גבול וקצה מסמנת למנגנון התיעוד לעבד את המידע הקיים לכן חשוב שכל הערה הנוגעת לממשק המחלקה (ורק הערה כזו) תיכתב בין הסימנים **/ ו- */. אם ההערה ארוכה משורה אחת, מקובל לפתוח כל שורה חדשה בהערה בסימן *. סימן זה הוא תוספת סגנונית שאינה הכרחית לפעולתו של מנגנון התיעוד. לפני שנמשיך, נציג לפניכם דף HTML המתעד חלק מהמחלקה,Bucket שבה עסקנו בפרק זה. קראו דף זה בעיון: Class Bucket public class Bucket extends java.lang.object המחלקה מגדירה דלי שהוא בעל קיבולת קיבולת זו הדלי יכול להכיל כמות מים כלשהי עד Version: 13.8.2007 Author: צוות מדעי המחשב, המרכז להוראת המדעים, האוניברסיטה העברית, ירושלים הפעולה בונה דלי ריק שקיבולתו היא הפרמטר capacity הפעולה מרוקנת את הדלי הנוכחי Constructor Summary Bucket(int capacity) Method Summary void empty() void fill(double amounttofill) הפעולה מקבלת כפרמטר כמות של מים וממלאת את הדלי הנוכחי בכמות זו. הפעולה מחזירה את הקיבולת של הדלי הנוכחי int getcapacity()

- 56 - עיצוב תוכנה מבוסס עצמים ג'אווה העיון בדפי התיעוד מעלה שאלות מעניינות רבות: 1. כיצד ידע המהדר לדווח בדפי התיעוד מי יצר את המחלקה, מתי עדכן אותה לאחרונה ומה היא מגדירה? 2. מניין לקח המהדר את התיאורים התמציתיים של הפעולות המתוארות במסמך? 3. מדוע שמות הפעולות נכתבות כאילו הן משמשות הפניה למקום נוסף?(link) ולמה מפנות הפעולות? נסכם בקצרה ונאמר כי המהדר מנתח את התיעוד הנכתב בגוף המחלקה, מעבד אותו למידע ומסכם את המידע עבור המשתמש בדפי ה- HTML. נבחן חלק מהתיעוד שגרם לפרטים חשובים אלה להופיע בתיעוד המחלקה: /** המחלקה מגדירה דלי שהוא בעל קיבולת * הדלי יכול להכיל כמות מים כלשהי עד קיבולת זו * צוות מדעי המחשב, המרכז להוראת המדעים, האוניברסיטה העברית, ירושלים @author * * @version 13.8.2007 */ public class Bucket // private attributes private int capacity; private double currentamount; /** הפעולה בונה דלי ריק שקיבולתו היא הפרמטר *.capacity הנחה : קיבולת הדלי היא מספר אי-שלילי * קיבולת הדלי @param capacity * */ public Bucket (int capacity) this.capacity = capacity; this.currentamount = 0; קל להבחין שהערות שנכתבו לפני כותרות המחלקה והפעולות (בכתיב מיוחד המשלב את הסימנים: / * @), עובדו, ושהטקסט המופיע בהן והמספק מידע לגבי המחלקה הודפס במסמך התיעוד. הסימון המיוחד @author גרם להדפסת שם יוצר המחלקה במסמך התיעוד, הסימון

פרק 3 מחלקות, הגדרה ובנייה - 57 - @version גרם להדפסת הגרסה בתיעוד, ותיאור הפעולות תועד אף הוא במסמך הסופי. חשוב לציין שהערות שסומנו ב-// אינן נראות במסמך התיעוד. הערות אלה אינן חלק מממשק המחלקה. בדף מעבדה בסוף הפרק מתוארים בפירוט ומתורגלים הכללים לכתיבת הערות ואופן הפקת מסמכי תיעוד. אין להמעיט בחשיבותו של תיעוד טוב, ובכל זאת בהמשך נקצר מאוד בהבאת התיעוד לפעולות ולמחלקות כדי שנוכל להתמקד בעיקר בלימוד הקוד ולמנוע את הסחת הדעת. בעבודתכם במעבדה תגלו שתיעוד טוב ומלא הכרחי בזמן עבודה עם מחלקות קיימות, ולכן בזמן העבודה במעבדה חשוב מאוד שתקפידו על תיעוד מלא ואמין. ט. איברי מחלקה Members) (Class בלימודיכם הקודמים כבר פגשתם את המילה השמורה static כמאפיין של פעולות. אולי כבר נתקלתם בלימודיכם עד כה בתכונות שבהגדרתן נכלל מאפיין זה. לצרכים שונים נגדיר איברים שונים בצירוף האפיון.static מה המשמעות של מילה זו? מהן פעולות ותכונות סטטיות? איברים סטטיים הם איברים השייכים למחלקה. תחילה נלמד מהן תכונות מחלקה ) class,(variables ובהמשך נערוך היכרות עם פעולות מחלקה methods).(class כזכור, תכונות ופעולות יחד נקראות איברים. ט. 1. תכונות מחלקה כל התכונות שהכרנו עד כה קרויות תכונות מופע variables),(instance משום שהן שייכות תמיד לעצם מסוים, ומשקפות את מצבו. לעומתן, קיימות תכונות מסוג אחר, אשר אינן שייכות לעצם מסוים, אלא למחלקה עצמה. תכונות אלה קרויות תכונות מחלקה. הן מוקצות בזיכרון בפעם הראשונה שנעשה שימוש במחלקה, וניתן לגשת אליהן, לקריאה או לשינוי, על ידי פנייה למחלקה. מדוע תכונות המחלקה הוגדרו כך? ייתכן שזו מחלקה שכלל לא נועדה שייצרו ממנה עצמים, אלא היא מספקת שירותים לעצמים ממחלקות אחרות. במקרה שכזה התכונות שלה מאחסנות ערכים הקשורים לשירותים אלה ולא למופעים. ייתכן שזו מחלקה שאמנם נוצרים ממנה עצמים, אך לנו יש עניין בתכונה שתוגדר עוד קודם להיווצרות המופעים, ותהיה משותפת לכלל המופעים. במקרה זה, תכונות המחלקה משקפות מצב משותף של כל העצמים שנוצרו מאותה מחלקה, ולא את מצבו של עצם זה או אחר. בהמשך הפתן לגרק נדגים את שני המצבים הללו. ט. 2. פנייה לתכונת מחלקה נישת לתכונות של מחלקה, תכונות סטטיות, בעזרת פנייה ישירה דרך שם המחלקה, או דרך כל אחד ממופעי המחלקה, כפי שנעשה בכל תכונה רגילה. בשני האופנים ניתן לשנות את ערכה של התכונה. שינוי זה ישפיע על כל מופעי המחלקה.

- 58 - עיצוב תוכנה מבוסס עצמים ג'אווה Bucket.capacity b1.capacity נדגים את שני האופנים של פנייה אל תכונת מחלקה שהוגדרה כפומבית: 1. דרך שם המחלקה: 2. דרך מופע מסוים של המחלקה: עבור מופע קיים b1// כאשר התכונה פרטית, מתאימות הקיימות בממשק בלבד. אזי הפנייה אליה תיעשה באותם שני האופנים, אך בעזרת פעולות הדרך העדיפה היא פנייה דרך שם המחלקה, בעזרת סימון הנקודה. באופן זה מודגש הרעיון שהתכונה היא של המחלקה עצמה. הדרך האחרת אפשרית גם היא, כיוון שכל מופע "מכיר" את המחלקה שלו ויכול להתייחס לתכונותיה, אך לא מומלץ להשתמש בה. דוגמה לתכונת מחלקה נדגים מהן האפשרויות הניתנות למשתמש בתכונות מחלקה, ונצביע על חסרונות הנובעים מכך. נחזור להגדרת המחלקה Bucket ונקבע כי קיבולת הדליים תהיה אחידה, כלומר נגדיר תכונה המשותפת לכל מופעי המחלקה. ערכה של הקיבולת עבור כל המופעים יהיה 5: public class Bucket תכונות (פרטיות ( // private static int capacity = 5; private double currentamount;... המקום בזיכרון עבור התכונה capacity מוקצה עוד לפני יצירת המופע הראשון שלה. לכל מופע מטיפוס "דלי" יש אפשרות גישה לתכונה זו. שינוי התכונה הנעשה על ידי מופע אחד משנה את הקיבולת של כל מופעי המחלקה. capacity 5 מרגע שהקיבולת הוגדרה כתכונת מחלקה נקבעים כמה כללים חדשים: יש רק העתק אחד של התכונה, והוא משותף לכל מופעי המחלקה. ניתן לראות את תוכנו של ההעתק דרך כל מופע, וניתן לשנותו מתוך כל מופע ואף ישירות מהמחלקה באופן הזה: Bucket.capacity = 7;

פרק 3 מחלקות, הגדרה ובנייה - 59 - ברוב המקרים הגישה הזו הניתנת למשתמש אינה מועילה ועלולה לגרור בעיקר נזקים. נציג מנגנון המאפשר להשאיר את התכונה משותפת לכל מופעי המחלקה, אך חוסם את התכונה מפני שינויים לא רצויים. ט. 3. תכונות קבועות ותכונות מחלקה ישנן תכונות שערכן נקבע פעם אחת בלבד והוא אינו צריך להשתנות לכל אורך התוכנית. אם היינו רוצים שקיבולת הדלי תהיה קבועה לכל הדליים שייווצרו בלי אפשרות של שינוי ערך זה, היינו מגדירים: public static final int CAPACITY = 5; הגדרה זו פירושה שיתקבל עותק אחד ויחיד בלתי ניתן לשינוי של התכונה קיבולת, שלו ערך קבוע, גלוי ומשותף לכל המופעים של המחלקה. ההגדרה הזו קובעת שזהו קבוע,(final) פומבי,(public) של המחלקה,(static) והוא מטיפוס הנתונים הבסיסי.int הצירוף של final ו- static הוא צירוף נפוץ מאוד בג'אווה. ניתן להגדיר את התכונה כפומבית אם רוצים שתופיע בממשק אך אז לא ניתן יהיה לשנות את ייצוג המחלקה. כמובן שאם התכונה הוגדרה כ- final לא ניתן לשנות את ערכה בעזרת פעולה כלשהי, כך שאין סכנה לפגיעה בהכמסה. מכיוון שזהו קבוע, שמו מופיע באותיות גדולות. אגב, גם זו מוסכמה של מתכנתי ג'אווה. נסכם את הנאמר לגבי התכונות: תכונת מופע variable) :(instance.1.2 מאפיינת מופע מסוים של המחלקה. לכל מופע יש עותק משלו של התכונה. שינוי ערך התכונה במופע אחד לא ישפיע על ערכי התכונה במופעים אחרים. למעשה, כל התכונות שכללנו בהגדרת המחלקה עד כה היו תכונות מופע. תכונת מחלקה variable) :(class.1.2 תכונה זו תופיע בצירוף המילה השמורה.static מאפיינת את המחלקה באופן כללי ולא מופע מסוים שלה. בזיכרון קיים עותק יחיד של תכונה זו, מהמחלקה. לכך יש שתי השלכות: א. ב. ללא קשר למספר המופעים שנוצרו תכונת מחלקה קיימת עוד לפני שנוצר המופע הראשון ואינה דורשת כלל יצירת מופעים. אם מופע מסוים שינה את ערכה של התכונה, ערכה החדש בא לידי ביטוי בכל המופעים.

- 60 - עיצוב תוכנה מבוסס עצמים ג'אווה ט. 4. פעולות מופע ופעולות מחלקה כל הפעולות שעסקנו בהן עד כה היו פעולות מופע methods),(instance כלומר פעולות שמבצע עצם מסוים (מופע) של המחלקה. פעולות מחלקה methods) (class הן פעולות שהמחלקה מבצעת, ולא מופע מסוים שלה. פעולות אלה ניתן לזמן גם בלי לבנות מופעים של המחלקה. נעיר כי הנוסח 'פעולות שהמחלקה מבצעת' אינו מדויק. בפועל, אנו מפעילים פעולה של המחלקה, כפי שאנו מפעילים את הפעולות של העצם, אך הנוסח הזה מתאים לתפיסה של עצמים כישויות אקטיביות המפעילות פעולות, ולכן נמשיך להשתמש בו. פעולות מחלקה לעולם אינן משתמשות בתכונות של מופעי המחלקה, בתכונות סטטיות של המחלקה. אך הן יכולות להשתמש נחזור לדוגמה הקודמת של התכונה :capacity public class Bucket תכונות (פרטיות ( // private static int capacity = 5; private double currentamount;... התכונה מוגדרת כסטטית, כלומר היא תכונה שאינה שייכת בנפרד ובאופן פרטי לשום מופע של המחלקה. נגדיר במחלקה Bucket את הפעולה.setCapacity() כיוון שהפעולה פונה לתכונה של המחלקה, היא תוגדר כפעולת מחלקה והאפיון static יופיע בכותרתה: public static void setcapacity (int capacity) Bucket.capacity = capacity; באופן דומה נגדיר גם את הפעולה getcapacity() כפעולת מחלקה בעזרת האפיון :static public static int getcapacity() return Bucket.capacity; הפעלה של פעולת מחלקה נעשית באותן שתי דרכים שפירטנו בפנייה לתכונות מחלקה ובאותן מגבלות שימוש שפורטו:.1 דרך שם המחלקה Bucket.getCapacity (capacity);.2 דרך מופע של אותה המחלקה (לא מומלץ) b1.getcapacity(); מהו הקריטריון שיקבע אם פעולה תוגדר כפעולת מופע או כפעולת מחלקה?

פרק 3 מחלקות, הגדרה ובנייה - 61 - כאשר פעולה אינה מתייחסת לתכונות של עצם ספציפי של המחלקה, אין סיבה שהיא תופעל על ידי עצם כלשהו. במקרה זה נגדיר אותה כפעולת מחלקה. כאשר פעולה פועלת על הפרמטר שקיבלה בלבד ולא על תכונות המחלקה, היא תוגדר כסטטית..1.2 ט. 5. הרחבת הממשק לעומת פעולות חיצוניות לעתים נרצה לבצע פעולה על מופע של מחלקה כלשהי אף שאינה מוגדרת בממשק מחלקה זו. למשל, נרצה להעביר מים מדלי אחד לאחר, כך שבסוף התהליך שני הדליים יהיו מלאים כל אחד בכמות מים שהיא הממוצע של המים שהיו בשני הדליים. כותרתה של פעולה שכזו צריכה להיראות כך: public void pouraverage (Bucket b1) אם יש אפשרות לשנות את הממשק, לפתוח את הקוד של המחלקה ולשנות אותו, אפשר להגדיר את הפעולה החדשה כפעולה פנימית, שתיאורה מופיע בממשק המחלקה. אך לעתים נרצה לבצע הוספה זו לגבי מחלקה שלא אנחנו הגדרנו אותה או מימשנו אותה. למחלקה שעברה הידור ושאת קוד המקור שלה אין לנו, לא נוכל להוסיף פעולה פנימית. ביחידה החמישית נלמד על מנגנון הירושה כדרך להתמודדות עם מטלה זו. בינתיים נוכל להיעזר ברעיון של פעולה חיצונית. הפעולה הרצויה תוגדר במחלקה אחרת מהמחלקה דלי, והיא תיקרא פעולה חיצונית למחלקה דלי. הפעולה אמנם מקבלת שני דליים כפרמטרים, אך היא אינה מופעלת מתוך אחד המופעים האלה, שכן היא אינה פעולה השייכת לעצם. השתייכותה למחלקה האחרת תגרור קרוב לוודאי להגדרתה שם כפעולת מחלקה, המכילה את האפיון static בכותרתה. נראה את קוד הפעולה. אנו מניחים שהקיבולת של כל אחד מהדליים גדולה או שווה לכמות המים הממוצעת: public static void pouraverageamount(bucket b1, Bucket b2) double averageamount = (b1.getcurrentamount() + b2.getcurrentamount())/2; b1.empty(); b2.empty(); b1.fill(averageamount); b2.fill(averageamount); הערות: 1. כאשר אנו מגדירים פעולה המקבלת כפרמטר עצם מטיפוס כלשהו, אנו מניחים בדרך כלל שהעצם המועבר כפרמטר קיים, כלומר שההפניה שהתקבלה כפרמטר אינה.null ללא הנחה מקדימה זו, וכאשר אין בקוד של הפעולה טיפול מיוחד במקרה שערך הפרמטר הוא,null התוכנית תופסק אם ננסה להפעיל פעולה של העצם. ההפסקה היא תוצאה של פנייה לפעולה של עצם שאינו קיים. הנחה זו מחייבת כל מי שמשתמש בפעולה שכתבנו. כיוון שהמצב הנפוץ

- 62 - עיצוב תוכנה מבוסס עצמים ג'אווה ביחידה זו הוא שערכי פרמטרים מטיפוסי עצמים אינם מקבלים ערך,null לא נוסיף הנחה זו לממשקי הפעולות. אם פעולה כלשהי בכל זאת נדרשת לטפל במקרה של הפניה שהיא,null הנחה זו תיכתב במפורש. שימו לב שהפעולה אינה מתבצעת במחשב כפי שהיינו מבצעים אותה במציאות. במשחק דליים מציאותי, בהנחה ש- b1 הוא הדלי שבו כמות המים הגדולה יותר ובהנחה שמוגדרת פעולת pourinto מתאימה, היינו מעבירים את הכמות המתאימה מדלי אחד לדלי האחר כך: b1.pourinto(b2,(b1.getcurrentamount() b2.getcurrentamount())/2);.2 או שהיינו נעזרים בדלי עזר נוסף כדי להעביר כמויות מדלי למשנהו עד שנגיע לכמות הרצויה בכל דלי. בתכנות, מכיוון שממילא איננו משתמשים במים אמיתיים אלא רק מייצגים כמויות על ידי מספרים, אנו "נפטרים" מכל המים על ידי ריקון הדליים ואז ממלאים אותם מחדש בדיוק בכמות הרצויה. אם נניח שהפעולה הוגדרה במחלקה BucketUtils המכילה פעולות על דליים, אזי כמו בכל פעולת מחלקה, זימונה ייעשה בעזרת שם המחלקה: BucketUtils.pourAverageAmount(b1, b2); לסיכום: פעולות חיצוניות למחלקה נתונה הן פעולות המשתמשות בעצמים הנוצרים מהמחלקה אך מופיעות במחלקה אחרת. לעתים הן יהיו מוגדרות במחלקה שבה נמצאת הפעולה הראשית, שגם היא כזכור פעולת מחלקה, לפני או אחרי הפעולה הראשית עצמה. ט. 6. מחלקות שירות פעולות מחלקה נפוצות במחלקות שירות, מטרתן העיקרית של מחלקות אלה אינה לשמש ליצירת עצמים. הן מכילות אוסף של פעולות בנושא מסוים, כולן פעולות מחלקה. כזו היא המחלקה השימושית,Math המכילה פעולות לביצוע חישובים מתמטיים שונים. איננו יוצרים מופעים של המחלקה, אך אנו משתמשים בפעולותיה כדי לבצע חישובים מתמטיים שונים. לדוגמה פעולת השורש sqrt של המחלקה.Math פעולה זו מקבלת מספר ומבצעת עליו את האלגוריתם של הוצאת שורש. כיוון שהיא לא משתמשת בתכונות מופע של Math היא פעולת מחלקה. במחלקה Math לא מוגדרות תכונות מופע, אך מוגדרות בה תכונות מחלקה: PI המייצגת את היחס בין היקף מעגל לקוטרו; ו- E המייצגת את בסיס הלוגריתמים הטבעיים, שהם מספרים שימושיים. את המחלקה Math אין צורך לייבא לתוכנית, כיוון שג'אווה מייבאת אותה תמיד. אין להסיק מכך שכל מחלקת שירות מיובאת תמיד באופן אוטומטי. לייבא את המחלקות הרצויות בצורה מפורשת. יש מקרים שבהם צריך ט. 7. הפעולה הראשית main( ) פעולת מחלקה שימושית ביותר המוכרת לנו היא הפעולה הראשית.main במבנה התוכניות שהכרנו עד כה, תוכנית מכילה מחלקה אחת ובה פעולת המחלקה,main ומחלקות נוספות שמהן

פרק 3 מחלקות, הגדרה ובנייה - 63 - מייצרים עצמים. הפעולה הראשית מופעלת מיד בתחילת הריצה של התוכנית, והפקודות שבה הן היוצרות עצמים ממחלקות אחרות ושולחות אליהם הודעות לביצוע פעולות. מכיוון שהפעולה הראשית היא הפעולה הראשונה שמבוצעת על ידי המערכת, עוד לפני יצירת מופע כלשהו, היא חייבת להיות מוגדרת כפעולת מחלקה. י. סיכום ניתן לראות את המחלקה כמגדירה טיפוס נתונים חדש, וכתבנית שממנה ניתן ליצור מופעים מטיפוס זה. מחלקה כוללת הצהרות על תכונות: אלה הם המשתנים הפנימיים של כל עצם הנוצר ממנה. משתנים אלה הם הייצוג של המחלקה. המשתנים מאותחלים בזמן יצירת העצם, והערכים שבהם יכולים להשתנות במהלך התוכנית. ערכי המשתנים מייצגים את מצבו של העצם ברגע נתון. בדרך כלל מוגדרות התכונות כפרטיות. השלבים בכתיבת מחלקה חדשה על פי ממשק נתון: 1. כותרת המחלקה. 2. ייצוג המחלקה: בחירת התכונות והטיפוסים שלהן. 3. מימוש פעולות ממשק המחלקה. פעולה בונה היא דרך לאתחל עצמים (מופעים) חדשים של המחלקה. מימוש פעולה בונה מאתחל את תכונות העצם בהתאם לפרמטרים המועברים לפעולה ובהתאם לשיקול הדעת של המתכנת, או על פי ברירות מחדל. רוב הפעולות המוגדרות במחלקה הן פעולות של העצמים. בעזרתן ניתן לגשת לתכונות, להשתמש בערכיהן ולשנות אותם. הרשאות הגישה מאפשרות לקבוע אילו איברים של העצמים יהיו נגישים ואילו לא, כאשר נמצאים מחוץ לקוד המחלקה. הרשאות הגישה מאפשרות הפרדה בין הממשק למימוש, ותומכות ברעיון ההכמסה. ההפרדה בין ממשק למימוש מאפשרת להחליף את ייצוג מחלקה ואופן מימושה מבלי שהמשתמש יהיה מודע לשינוי. כאשר קיימת הפרדה מלאה נתייחס למחלקה כאל טיפוס נתונים מופשט. אל פעולות פומביות, כולל הפעולה הראשית,main( ) ניתן לפנות מתוך מחלקות אחרות, בניגוד לפעולות פרטיות שאליהן ניתן לפנות רק מתוך קוד המחלקה עצמה. מנגנון התיעוד Javadoc מאפשר ליישם את העיקרון של עבודה עם ממשקים, שהוא מעמודי התווך של תכנות מונחה עצמים. בעזרת מנגנון זה תוכלו לייצר בקלות תיעוד לממשקים בעבור מתכנתים אחרים המשתמשים במחלקות שכתבתם. התיעוד נוצר על פי קוד המחלקה המתועד. מנגנון ההעמסה מאפשר להגדיר במחלקה אחת פעולות שלהן אותו השם, אך רשימת פרמטרים שונה. אחת הפעולות השימושיות תהיה פעולה בונה מעתיקה, שתשמש לשכפול עצמים.

- 64 - עיצוב תוכנה מבוסס עצמים ג'אווה תכונות מחלקה הן תכונות השייכות למחלקה ולא למופע מסוים שלה. תכונות אלה נגישות מתוך כל מופע של המחלקה, וכן ישירות מהמחלקה. פעולות מחלקה הן פעולות המבוצעות על ידי המחלקה ואינן משתמשות בתכונות מופע. דוגמה לכך הן פעולות שירות של המחלקה.Math פעולות מחלקה, ובכלל זה הפעולה הראשית, ניתנות להפעלה גם קודם ליצירת מופע כלשהו. פעולות פנימיות הן פעולות המופיעות בממשק מחלקה. פעולות חיצוניות הן פעולות המקבלות פרמטר מטיפוס המחלקה, אך מוגדרות מחוץ למחלקה עצמה. דרך נוחה להצגת מחלקות היא תרשימי.UML דרך נוחה להצגת עצמים היא בעזרת תרשימי עצמים. מושגים class members this overloading access specifiers abstract data type (ADT) class header javadoc Static public default constructor copy constructor private איברי מחלקה הנוכחי העמסה הרשאות גישה טיפוס נתונים מופשט כותרת מחלקה מנגנון התיעוד של ג'אווה סטטי (=של המחלקה) פומבי פעולה בונה ברירת מחדל פעולה בונה מעתיקה פרטי

פרק 3 מחלקות, הגדרה ובנייה - 65 - עבודה מס' 1 דף 3 פרק התחלה נקודת חלק א: המחלקה Point בפרק הקודם השתמשנו במחלקה הקיימת,Point ועתה נלמד לכתוב מחלקה שדומה לה. ממשק המחלקה Point המחלקה Point שנבנ ה בתרגיל זה מגדירה נקודה בעלת שתי קואורדינטות: x ו- y. Point (double x, double y) double getx() void setx (double x) double gety() void sety (double y) String tostring() הפעולה בונה נקודה חדשה על פי ערכי הפרמטרים הפעולה מחזירה את קואורדינטת ה- x של הנקודה הפעולה מקבלת ערך מטיפוס,double וקובעת את קואורדינטת ה- x של הנקודה בהתאם הפעולה מחזירה את קואורדינטת ה- y של הנקודה הפעולה מקבלת ערך מטיפוס,double וקובעת את קואורדינטת ה- y של הנקודה בהתאם הפעולה מחזירה מחרוזת המתארת את נתוני הנקודה על פי הצורה הבאה : ( <X>, <Y> ) מה עליכם לעשות? צרו מחלקה חדשה בשם Point (זכרו: שם המחלקה ושם הקובץ שבו היא נמצאת חייבים א. להיות זהים). יצגו את המחלקה Point (במילים אחרות: קבעו מה יהיו התכונות של מופעי המחלקה). ב. ציירו תרשים UML המתאים למחלקה. ג. ממשו את פעולות המחלקה.Point ד. כדי לבדוק שהמחלקה שכתבתם עובדת כראוי, עליכם לכתוב תוכנית בדיקה, לפי ההנחיות האלה:

- 66 - עיצוב תוכנה מבוסס עצמים ג'אווה המחלקה TestPoint צרו מחלקה נוספת בשם TestPoint (בקובץ.(TestPoint.java בתוך המחלקה TestPoint כתבו פעולת main(...) המבצעת את משימות האלה: (7,43). בונה נקודה חדשה לפי הקואודינטות 1. בונה נקודה חדשה נוספת לפי הקואורדינטות (5,5). 2. מדפיסה את שתי הנקודות בעזרת המחרוזת המוחזרת מהפעולה tostring() כך (אין צורך 3. לכתוב את שם הפעולה במפורש): System.out.println (xxx); מחליפה בין קואורדינטות ה- x של שתי הנקודות, תוך שימוש בפעולות השונות של המחלקה 4. נקודה. מדפיסה שוב את הנקודות החדשות. 5. חלק ב: נרחיב את המחלקה Point ונוסיף לה שתי פעולות: double distance (Point p) Point middle (Point p) הפעולה מקבלת נקודה ומחזירה את המרחק שבינה לבין הנקודה הנוכחית (ראו למטה תזכורת לחישוב המרחק) הפעולה מקבלת נקודה ומחזירה את הנקודה הנמצאת בין הנקודה שהתקבלה כפרמטר ובין הנקודה הנוכחית באמצע x 1 + x x 2 middle = 2 תזכורת: חישוב נקודת האמצע בין שתי הנקודות ) 1 (x 1, y ו-( (x 2, y 2 הוא: y 1 + y y 2 middle = 2 חישוב המרחק בין שתי נקודות( (x 1, y 1 ו-( (x 2, y 2 הוא: ( x y 2 2 1 x2 ) + ( y1 2 ) פעולות החזקה והשורש קיימות במחלקה Math המופיעה במאגר המחלקות המוכנות של ג'אווה (ראו ב- API ). Math נמצאת בתוך החבילה הסטנדרטית,java.lang ולכן אין צורך "לייבא" אותה. ממשק חלקי של המחלקה Math המחלקה מאגדת בתוכה פעולות מחלקה שונות המבצעות חישובים מתמטיים נפוצים. double pow (double x, double y) double sqrt (double x) הפעולה מקבלת שני פרמטרים y בחזקת x את הערך של ומחזירה ו- y, x הפעולה מקבלת את הפרמטר x ומחזירה את השורש הריבועי שלו

פרק 3 מחלקות, הגדרה ובנייה - 67 - הפעולות האלה הן פעולות מחלקה. להוציא שורש מ- 9 יש לכתוב: הפעלת הפעולות נעשית דרך שם המחלקה. לדוגמה, כדי double root = Math.sqrt(9); הוסיפו לפעולה הראשית חישוב של המרחק בין שתי הנקודות המקוריות שיצרתם בחלק א, והדפיסו אותו. הוסיפו לפעולה הראשית חישוב של נקודת האמצע בין הנקודות שיצרתם בחלק א, לאחר החלפת ערכי ה- x. הדפיסו את הנקודה..1.2 שימו לב: בפעולה המחשבת נקודת אמצע, ערך ההחזרה גם הוא עצם מסוג.Point כלומר עליכם ליצור את העצם החדש בתוך מימוש הפעולה, ואז להחזיר אותו כערך ההחזרה של הפעולה. בהצלחה!

- 68 - עיצוב תוכנה מבוסס עצמים ג'אווה עבודה מס' 2 דף 3 פרק Javadoc תיעוד רקע בדף עבודה זה נלמד להשתמש במנגנון התיעוד.Javadoc מנגנון זה מאפשר לייצר דפי HTML סטנדרטיים, בעלי אופי אחיד, המכילים את הממשק למשתמש בפורמט המוכר לכם מדפי ה- API שאתם עבדתם. דפי הממשק מיוצרים על פי ההערות שהוספתם לקוד, ובתנאי שההערות נכתבו בפורמט הנכון. התיעוד האחיד מאפשר שימוש נוח במחלקות שונות על ידי משתמשים רבים. ההערות המיועדות להפקת דפי תיעוד חיצוניים מכילות נתונים שונים שמהם המהדר מתעלם, ומנגנון התיעוד משתמש בהם כדי לתרגם אותם למידע משמעותי בדף הממשק. כך למשל, כל פרמטר הנשלח לפעולה וכל ערך החזרה של פעולה יפורטו בדף הממשק. בשלב התיעוד יופיע בהערה סימן @ ולידו הסבר לגבי מהות הפרמטר או ערך ההחזרה. בדף הממשק יתקבלו מסימון זה שורות מידע מסודרות. מה עליכם לעשות? עליכם לתעד את הקוד של המחלקה,Point שכתבתם בדף העבודה הקודם, תוך שימוש בתיעוד האוטומטי של סביבת ה- Eclipse. לאחר שהגדרתם כותרת של פעולה, עלו עם הסמן לשורה שמעל לכותרת הפעולה (ניתן לבצע אותו תהליך לגבי כותרת של מחלקה), כתבו **/ והקלידו Enter (שימו לב שעליכם להקליד שתי כוכביות). באופן אוטומטי תופיע מעל כותרת הפעולה הערה המסתיימת ב-/*. בתוכה יופיעו סימני ה- Javadoc הרלוונטיים: @author username אם זו כותרת מחלקה void אם הפעולה אינה @returns @param אם יש פרמטרים, וכו'. השלימו את התיעוד הנדרש ליד כל סימן @. הערה: ביכולתכם לתעד כל מחלקה אחרת שכתבתם, אך השתדלו שזו תכיל מגוון פעולות ולא רק פעולת,main כך שתוכלו להתרשם מהממשק המתקבל. הפעלת מנגנון התיעוד 1. ברשימת התפריטים בחלק העליון של חלון סביבת העבודה, יש לבחור את תפריט,Project ובתוכו את.Generate Javadoc 2. בחרו בהמשך המסך את הפרויקט שעבורו אתם רוצים ליצור את התיעוד, על ידי סימונו במקום המתאים. אם ברצונכם לייצר ממשק רק לחלק ממחלקות הפרויקט (לדוגמה, אם אתם רוצים לוותר על יצירת תיעוד לספריות), ניתן ללחוץ על Next ולבחור ספציפית עבור אילו מחלקות ייווצר.Javadoc

פרק 3 מחלקות, הגדרה ובנייה - 69 - כברירת מחדל קובצי ה- HTML של ה- Javadoc ייווצרו תחת ספריית הפרויקט שלכם, בתת-ספרייה בשם.doc אישור הביצוע בשלב זה ימקם את קובץ התיעוד באותה ספרייה שבה שמור הפרויקט שלכם, בתת-ספרייה בשם.doc אם ברצונכם לשמור את התיעוד במקום אחר בחרו את המיקום בשלב זה. לאחר אישור הפעולה ידווח המהדר דיווחים שונים בחלון ה- Console. אל תיבהלו, הרשימה ארוכה, אך בסוף התהליך יתוספו לפרויקט שלכם, בחלון ה- Explorer,Package תיקיות התיעוד של הפרויקט. פתחו את תיקיית ה- doc וחפשו את הקובץ הנושא את שם המחלקה שבה אתם מעוניינים. סיומת הקובץ תהיה.html פתחו את קובץ ה-' html '. עברו על הקובץ והשוו בין התיעוד שנוצר לתיעוד שכתבתם אתם במחלקה..3.4 סימני תיעוד למנגנון התיעוד אפשרויות רבות, אוטומטי: א. שם כותב המחלקה ואנו נציג בפירוט שלוש מתוכן, שמתוספות להערות באופן בתוך גוף ההערה המתעדת את המחלקה יתוסף הכיתוב @author.<yourname> לאחר הכיתוב @author עליכם להוסיף את שמכם. לדוגמה: /** * This class represents a... * @author Zrubavela Yakinton. */

- 70 - עיצוב תוכנה מבוסס עצמים ג'אווה ב. שימו לב לסימן @, המופיע לפני הפקודה.author סימן זה מופנה אל מנגנון ה- Javadoc, התיעוד במקום המתאים. פרמטרים של פעולה ומורה לו להתייחס לאינפורמציה המופיעה לאחר ה-@ הפרמטרים הנשלחים אליה, ולהוציאה אל דף מנגנון התיעוד ישלוף מתוך הסוגריים של הפעולה את רשימת ויציין אותם בעזרת @param הסבר למהות הפרמטרים, השלימו את ההסבר בהמשך לסימון. לדוגמה, את הפעולה: נוכל לתעד על ידי: בתוך גוף ההערה. כדי להוסיף void setx(double x) /** * changes the x coordinate to the given value. * @param x the new value for the x coordinate. */ ג. ערך החזרה כדי להוסיף את פירוט ערך ההחזרה של פעולה, נשתמש בפקודה.@return לדוגמה, את הפעולה: נוכל לתעד על ידי : double gety() /** * returns the y coordinate. * @return the y coordinate. */ גם בשני מקרים אלה ישלוף מנגנון התיעוד את האינפורמציה שמופיעה לצד ה-@ וימקם אותה במקום הנכון בדף הממשק. בדקו! מידע נוסף על תוכנת התיעוד Javadoc תוכלו למצוא באתר חברת סאן: http://java.sun.com/j2se/javadoc/index.html כעת, כשאתם יודעים לעבוד עם ממשקים למשתמש וגם לייצר אותם, הקפידו לתעד כל מחלקה שתכתבו על פי הכללים החדשים. כך תוכלו לאפשר למשתמשים אחרים לעבוד עם המחלקות שכתבתם בעזרת דפי ה- HTML, מבלי להזדקק לקוד המקור. תקציר התגיות של Javadoc בטבלה שלהלן מצורפות כמה תגיות שמורות של מנגנון התיעוד.Javadoc את הפירוט המלא של התגיות תוכלו למצוא באתר של חברת סאן:.www.java.sun.com כדי להוסיף תגית חדשה עליכם להקליד @ בתוך ההערה ולבחור את התגית הרצויה מתוך חלון האפשרויות שנפתח. התגית משמעות התגית @author שם מחבר המחלקה @param פרמטר המועבר לשיטה @return הערך שמחזירה השיטה @see הפניה למחלקה אחרת הקשורה למחלקה זו גרסת המחלקה @version בהצלחה!

פרק 3 מחלקות, הגדרה ובנייה - 71 - עבודה מס' 3 דף 3 פרק בקוביות משחק ממשק המחלקה קובייה Die המחלקה Die (קובייה) מגדירה קובייה שלה 6 פאות. על הפאות מופיעים המספרים 1 עד 6. כאשר הקובייה נמצאת במנוחה, ונשאלת השאלה "מהו המספר שהקובייה מראה?" התשובה לכך היא: "המספר שנמצא על הפאה העליונה". Die() void roll() int getnum() הפעולה בונה עצם מטיפוס.Die הקובייה שנוצרה מראה מספר אקראי בין 1 ל- 6 הפעולה מדמה "הטלת קובייה". בתום הפעולה מתעדכן המספר שהקובייה מראה לאחר ההטלה הפעולה מחזירה את המספר שמראה הקובייה מה עליכם לעשות? 1. ח שבו מהן התכונות הנחוצות למחלקה Die וציירו UML מתאים למחלקה. 2. כתבו את המחלקה Die במלואה (כולל תיעוד ויצירת קובץ.(HTML רמז: כדי להטיל את הקוביות באופן אקראי השתמשו בפעולה random() של המחלקה.Math על אופן פעולתה ראו ב- API.Java 3. כתבו מחלקה בשם DiceGame (משחק קוביות), ובה פעולה ראשית היוצרת שתי קוביות. בכל תור תטיל התוכנית את שתי הקוביות עד אשר יתקבל הצירוף: 6. 6, בכל תור יש למעשה שתי הטלות של שתי קוביות המשחק. 4. התוכנית תדפיס את תוצאות ההטלות בכל התורות. 5. כאשר יתקבל הצירוף 6 6, תיעצר התוכנית ותדפיס כמה תורות התקיימו עד אשר קיבלנו 6. 6, 6. תעדו את המחלקה במלואה. הפעילו את מנגנון התיעוד Javadoc וודאו שהתקבל קובץ HTML מתאים המתעד את המחלקה כראוי. בהצלחה!